'''
Created on Apr 6, 2011

@author: glow
'''

import os
from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.api import users

from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden

import xml
import httplib

from models import Organisation, CDISC_Codelist, \
                    CDISC_CodeListItem, Controlled_Terminology_Source

from django.shortcuts import render_to_response

def index(response):
  return HttpResponse('Hello World')


class MyTemplate(webapp.RequestHandler):
  """
  from http://waoewaoe.wordpress.com/2011/01/09/global-template-system-in-google-app-engine/
  """
  def render(self, template_name, param):
    template_values = dict({'template_name': template_name}, ** param)
    path = os.path.join(os.path.dirname(__file__) + '/view', 'my_template.html')
    self.response.out.write(template.render(path, template_values))

class MainPage(MyTemplate): # extend MyTemplate
  def get(self):
    template_values = {'content' : 'hello world'}
    # calls render function from super class (MyTemplate)
    self.render('index.html', template_values)

def login_required(func):
  """
  Decorator that redirects to the login page if you're not logged in.
  taken from http://code.google.com/p/rietveld/source/browse/trunk/codereview/views.py
  """

  def login_wrapper(request, *args, **kwds):
    if request.user is None:
      return HttpResponseRedirect(
          users.create_login_url(request.get_full_path().encode('utf-8')))
    return func(request, *args, **kwds)

  return login_wrapper

def admin_required(func):
  """
  Decorator that insists that you're logged in as administratior.
  taken from http://code.google.com/p/rietveld/source/browse/trunk/codereview/views.py
  """

  def admin_wrapper(request, *args, **kwds):
    if request.user is None:
      return HttpResponseRedirect(
          users.create_login_url(request.get_full_path().encode('utf-8')))
    if not request.user_is_admin:
      return HttpResponseForbidden('You must be admin in for this function')
    return func(request, *args, **kwds)

  return admin_wrapper


    
def merge_terminology(context):
  import xml.etree as etree
  _namespace = {}
  def _ns(item, namespace):
    return "%s%s" % (_namespace.get(namespace), item)
  if context.startswith('CDISC'):
    _namespace = {'xs': '{http://www.w3.org/2001/XMLSchema-instance}', 
                  'odm': '{http://www.cdisc.org/ns/odm/v1.3}', 
                  'nciodm': '{http://ncicb.nci.nih.gov/xml/odm/ES/CDISC}'}
    # define the CDISC Org
    cdisc = Organisation.get_or_insert(name = 'CDISC',
                                       url = 'http://www.cdisc.org')
    for specification in ['cdash', 'sdtm']:
      try:
        conn = httplib.HTTPConnection("evs.nci.nih.gov")
        # do the SDTM 
        conn.request("GET", "/ftp1/CDISC/SDTM/%s-terminology.odm.xml" % specification)
        resp = conn.getresponse()
        if not resp.status == '200':
          return "FAIL: %s:%s" % (resp.status, resp.reason)
        # read the content
        content = resp.read()
        conn.close()
      except Exception, e:
        return ('FAIL: ' + str(e))
    tree = etree.ElementTree.fromstring(content)
    root = tree.getroot()
    source = Controlled_Terminology_Source.get_or_insert(organisation=cdisc,
                                                         name='CDISC Controlled Terminology %s' % specification.upper(),
                                                         description='CDISC Controlled Terminology %s' % specification.upper(),
                                                         url = 'http://evs.nci.nih.gov/ftp1/CDISC/SDTM/%s-terminology.odm.xml' % specification,
                                                         )
    for codelist in root.findall(".//%s" % _ns('CodeList', 'odm')):
      # Extract all attributes
      OID = codelist.get('OID')
      DataType = codelist.get('DataType')
      Name = codelist.get('Name')
      Extensible = codelist.get(_ns('CodeListExtensible', 'nciodm'))
      ExternalCodeID = codelist.get(_ns('ExtCodeID', 'nciodm'))
      CDISCDefinition = codelist.find(_ns('Description', 'odm')).text
      CDISCSubmissionValue = codelist.find(_ns('CDISCSubmissionValue', 'nciodm')).text
      # this always evals to a list
      CDISCSynonym = [x.text for x in codelist.findall(_ns('CDISCSynonym', 'nciodm'))]
      PreferredTerm = codelist.find(_ns('PreferredTerm', 'nciodm')).text
      # iterate
      cl = CDISC_Codelist.get_or_insert(ExternalCodeID=ExternalCodeID,
                                        Extensible=Extensible,
                                        Name=Name,
                                        CDISCDefinition=CDISCDefinition,
                                        CDISCSubmissionValue=CDISCSubmissionValue,
                                        OID=OID,
                                        DataType=DataType,
                                        CDISCSynonym=CDISCSynonym,
                                        PreferredTerm=PreferredTerm,
                                        Source = source)
      for EnumeratedItem in codelist.findall(_ns('EnumeratedItem', 'odm')):
        CDISCSynonym = [x.text for x in EnumeratedItem.findall(_ns('CDISCSynonym', 'nciodm'))]
        CDISCDefinition = EnumeratedItem.find(_ns('Description', 'odm')).text
        PreferredTerm = EnumeratedItem.find(_ns('PreferredTerm', 'nciodm')).text
        ExternalCodeID = EnumeratedItem.get(_ns('ExtCodeID', 'nciodm'))
        CDISCSubmissionValue = EnumeratedItem.get(_ns('CodedValue', 'odm'))
        ci = CDISC_CodeListItem.get_or_insert(ExternalCodeID=ExternalCodeID,
                                              CDISCSubmissionValue=CDISCSubmissionValue,
                                              CDISCSynonym=CDISCSynonym,
                                              PreferredTerm=PreferredTerm,
                                              Source = source)
        if not cl.key() in ci.Codelists:
          ci.Codelists.append(cl.key())                                        
  else:
    pass
     
class UpdateTerminology(webapp.RequestHandler):
  """
  Prompt the System to renew it's CT sources
  - NCI CT
    - http://evs.nci.nih.gov/ftp1/CDISC/SDTM/cdash-terminology.odm.xml
    - http://evs.nci.nih.gov/ftp1/CDISC/SDTM/sdtm-terminology.odm.xml
  - TODO: ADT 
  """
  def get(self):
    sources = Controlled_Terminology_Source.all()
    return render_to_response('controlledt.html', 
                              {'sources' : sources})
  
  @admin_required
  def post(self):
    if self.request.get('TYPE') == 'CDISC':
      merge_terminology('CDISC')
    
      

def codelist(request):
  pass
